#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
智能巡检车后端API服务器
纯API服务，支持跨域请求
"""

from flask import Flask, request, jsonify
from flask_cors import CORS
import os
import time
import sys
import serial
from Rosmaster_Lib import Rosmaster
import threading
import json
import logging
from datetime import datetime

# 创建Flask应用
app = Flask(__name__)

# 配置CORS，允许所有域名访问
CORS(app, origins="*", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"])

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 全局配置
CONFIG = {
    "DEBUG": True,
    "HOST": "0.0.0.0",
    "PORT": 5222,
    "MAX_SPEED": 100,
    "MIN_SPEED": 0,
    "SERIAL_PORT": "/dev/ttyUSB0",
    "DEFAULT_SPEED": 50,
    "SERIAL_BAUDRATE": 115200
}

class CarController:
    """智能巡检车控制器"""
    
    def __init__(self, debug=True):
        self.debug = debug
        self.bot = None
        self.is_moving = False
        self.current_state = 0
        self.current_speed = 0

        self.trace_mode = 0 #循迹模式标记
        self.trace_status = "stopped" #循迹下运动状态

        self.last_command_time = None
        self.connection_status = False
        self.serial_connection_status = False

        self.PTO_HEAD = 0xFF #串口协议头
        self.PTO_DEVICE_ID = 0xFC
        self.FUN_CAR_TRACE = 0x36

        self.TRACE_MODE_STOP = 0 #循迹状态定义
        self.TRACE_MODE_START = 1
        self.TRACE_MODE_PAUSE = 2
        self.TRACE_MODE_RESUME = 3

        self.init_robot()
        self.init_serial()
    
    def init_robot(self):
        """初始化机器人连接"""
        try:
            logger.info("正在初始化机器人连接...")
            self.bot = Rosmaster(debug=self.debug)
            self.bot.create_receive_threading()
            time.sleep(0.1)
            
            # 测试连接
            try:
                version = self.bot.get_version()
                logger.info(f"机器人连接成功，固件版本: {version}")
                self.connection_status = True
            except Exception as e:
                logger.warning(f"无法获取固件版本: {e}")
                self.connection_status = True  # 假设连接成功
                
        except Exception as e:
            logger.error(f"机器人初始化失败: {e}")
            self.bot = None
            self.connection_status = False

    def init_serial(self):
        """初始化串口连接"""
        try:
            logger.info(f"正在初始化串口连接: {CONFIG['SERIAL_PORT']}")
            self.serial_port = serial.Serial(
                CONFIG['SERIAL_PORT'], 
                CONFIG['SERIAL_BAUDRATE'], 
                timeout=1
            )
            self.serial_connection_status = True
            logger.info("串口连接成功")
        except Exception as e:
            logger.error(f"串口初始化失败: {e}")
            self.serial_port = None
            self.serial_connection_status = False
    
    def calculate_checksum(self, data):
        """计算校验和"""
        return sum(data) & 0xFF

    def send_trace_command(self, mode):
        """发送循迹控制命令
        
        Args:
            mode (int): 循迹模式 0=停止, 1=启动, 2=暂停, 3=恢复
        
        Returns:
            dict: 操作结果
        """
        if not self.serial_port or not self.serial_connection_status:
            return {
                "success": False,
                "message": "串口未连接",
                "code": "SERIAL_NOT_CONNECTED"
            }
        
        # 参数验证
        if not isinstance(mode, int) or mode < 0 or mode > 3:
            return {
                "success": False,
                "message": "无效的循迹模式参数",
                "code": "INVALID_TRACE_MODE"
            }
        
        try:
            # 构建数据包
            # 格式: HEAD(1) + DEVICE_ID(1) + LENGTH(1) + FUNC(1) + MODE(1) + CHECKSUM(1)
            data_payload = [self.FUN_CAR_TRACE, mode]
            length = len(data_payload)
            
            packet = [
                self.PTO_HEAD,      # 包头1
                self.PTO_DEVICE_ID, # 包头2  
                length,             # 数据长度
            ] + data_payload
            
            # 计算校验和
            checksum = self.calculate_checksum(packet[2:])  # 从长度字段开始计算
            packet.append(checksum)
            
            # 发送数据
            self.serial_port.write(bytearray(packet))
            
            # 更新状态
            self.trace_mode = mode
            mode_names = {
                self.TRACE_MODE_STOP: "stopped",
                self.TRACE_MODE_START: "running",
                self.TRACE_MODE_PAUSE: "paused", 
                self.TRACE_MODE_RESUME: "running"
            }
            
            mode_desc = {
                self.TRACE_MODE_STOP: "停止循迹",
                self.TRACE_MODE_START: "启动循迹",
                self.TRACE_MODE_PAUSE: "暂停循迹",
                self.TRACE_MODE_RESUME: "恢复循迹"
            }
            
            self.trace_status = mode_names.get(mode, "unknown")
            self.last_command_time = datetime.now()
            
            logger.info(f"循迹控制: {mode_desc.get(mode)} - 数据包: {[hex(x) for x in packet]}")
            
            return {
                "success": True,
                "message": mode_desc.get(mode, f"循迹模式{mode}"),
                "data": {
                    "mode": mode,
                    "status": self.trace_status,
                    "packet": [hex(x) for x in packet]
                }
            }
            
        except Exception as e:
            logger.error(f"发送循迹命令失败: {e}")
            return {
                "success": False,
                "message": f"发送循迹命令失败: {str(e)}",
                "code": "TRACE_COMMAND_ERROR"
            }
    
    def start_trace(self):
        """启动循迹"""
        return self.send_trace_command(self.TRACE_MODE_START)
    
    def stop_trace(self):
        """停止循迹"""
        return self.send_trace_command(self.TRACE_MODE_STOP)
    
    def pause_trace(self):
        """暂停循迹"""
        return self.send_trace_command(self.TRACE_MODE_PAUSE)
    
    def resume_trace(self):
        """恢复循迹"""
        return self.send_trace_command(self.TRACE_MODE_RESUME)
    
    def move_car(self, state, speed=None):
        """控制小车运动
        
        Args:
            state (int): 运动状态 0=停止, 1=前进, 2=后退, 3=左转, 4=右转, 5=左旋, 6=右旋
            speed (int): 速度 0-100，如果为None则使用当前速度
        
        Returns:
            dict: 操作结果
        """
        if not self.bot:
            return {
                "success": False, 
                "message": "机器人未连接", 
                "code": "ROBOT_NOT_CONNECTED"
            }

        if self.trace_status=="running":#开始运动自动关闭循迹
            self.stop_trace()
        
        # 使用传入的速度或当前速度
        if speed is None:
            speed = self.current_speed
        
        # 参数验证
        if not isinstance(state, int) or state < 0 or state > 6:
            return {
                "success": False, 
                "message": "无效的运动状态参数", 
                "code": "INVALID_STATE"
            }
        
        if not isinstance(speed, int) or speed < CONFIG["MIN_SPEED"] or speed > CONFIG["MAX_SPEED"]:
            return {
                "success": False, 
                "message": f"速度必须在{CONFIG['MIN_SPEED']}-{CONFIG['MAX_SPEED']}之间", 
                "code": "INVALID_SPEED"
            }
        
        try:
            self.bot.set_car_run(state, speed)
            self.current_state = state
            self.current_speed = speed
            self.is_moving = (state != 0)
            self.last_command_time = datetime.now()
            
            state_names = {
                0: "停止", 1: "前进", 2: "后退", 
                3: "左转", 4: "右转", 5: "左旋", 6: "右旋"
            }
            
            logger.info(f"小车控制: {state_names.get(state)} - 速度: {speed}")
            
            return {
                "success": True, 
                "message": f"小车{state_names.get(state, '未知')}，速度: {speed}",
                "data": {
                    "state": state,
                    "speed": speed,
                    "state_name": state_names.get(state, "未知")
                }
            }
            
        except Exception as e:
            logger.error(f"小车控制失败: {e}")
            return {
                "success": False, 
                "message": f"控制失败: {str(e)}", 
                "code": "CONTROL_ERROR"
            }
    
    def beep(self, duration=500):
        """控制蜂鸣器
        
        Args:
            duration (int): 响的时间(毫秒)，0=关闭，1=持续响，>=10=响指定毫秒
        
        Returns:
            dict: 操作结果
        """
        if not self.bot:
            return {
                "success": False, 
                "message": "机器人未连接", 
                "code": "ROBOT_NOT_CONNECTED"
            }
        
        if not isinstance(duration, int) or duration < 0:
            return {
                "success": False, 
                "message": "无效的时长参数", 
                "code": "INVALID_DURATION"
            }
        
        try:
            self.bot.set_beep(duration)
            
            if duration == 0:
                message = "蜂鸣器关闭"
            elif duration == 1:
                message = "蜂鸣器持续响"
            else:
                message = f"蜂鸣器响{duration}毫秒"
            
            logger.info(f"蜂鸣器控制: {message}")
            
            return {
                "success": True, 
                "message": message,
                "data": {"duration": duration}
            }
            
        except Exception as e:
            logger.error(f"蜂鸣器控制失败: {e}")
            return {
                "success": False, 
                "message": f"蜂鸣器控制失败: {str(e)}", 
                "code": "BEEP_ERROR"
            }
    
    def stop(self):
        """停止小车"""
        return self.move_car(0, 0)
    
    def get_status(self):
        """获取小车详细状态"""
        state_names = {
            0: "停止", 1: "前进", 2: "后退", 
            3: "左转", 4: "右转", 5: "左旋", 6: "右旋"
        }
        
        trace_mode_names = {
            0: "停止", 1: "启动", 2: "暂停", 3: "恢复"
        }

        return {
            "robot_connected": self.connection_status,
            "serial_connected": self.serial_connection_status,
            "is_moving": self.is_moving,
            "current_state": self.current_state,
            "current_speed": self.current_speed,
            "trace_mode": self.trace_mode,
            "trace_status": self.trace_status,
            "trace_mode_name": trace_mode_names.get(self.trace_mode, "未知"),
            "state_name": state_names.get(self.current_state, "未知"),
            "last_command_time": self.last_command_time.isoformat() if self.last_command_time else None,
            "server_time": datetime.now().isoformat()
        }
    
    def get_health(self):
        """健康检查"""
        return {
            "status": "healthy" if self.connection_status else "unhealthy",
            "robot_connected": self.connection_status,
            "uptime": time.time(),
            "version": "1.0.0"
        }

# 创建控制器实例
car_controller = CarController(debug=CONFIG["DEBUG"])

# ===== API路由定义 =====

@app.route('/api/health', methods=['GET'])
def api_health():
    """健康检查接口"""
    health = car_controller.get_health()
    status_code = 200 if health["status"] == "healthy" else 503
    return jsonify(health), status_code

@app.route('/api/status', methods=['GET'])
def api_status():
    """获取小车状态"""
    status = car_controller.get_status()
    return jsonify({
        "success": True,
        "data": status
    })

@app.route('/api/move', methods=['POST'])
def api_move():
    """控制小车运动"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({
                "success": False, 
                "message": "请求数据不能为空",
                "code": "EMPTY_DATA"
            }), 400
        
        state = data.get('state')
        speed = data.get('speed', CONFIG["DEFAULT_SPEED"])
        
        if state is None:
            return jsonify({
                "success": False, 
                "message": "缺少必要参数: state",
                "code": "MISSING_STATE"
            }), 400
        
        result = car_controller.move_car(state, speed)
        status_code = 200 if result["success"] else 400
        return jsonify(result), status_code
        
    except Exception as e:
        logger.error(f"API move error: {e}")
        return jsonify({
            "success": False, 
            "message": "服务器内部错误",
            "code": "INTERNAL_ERROR"
        }), 500

@app.route('/api/beep', methods=['POST'])
def api_beep():
    """控制蜂鸣器"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({
                "success": False, 
                "message": "请求数据不能为空",
                "code": "EMPTY_DATA"
            }), 400
        
        duration = data.get('duration', 500)
        
        result = car_controller.beep(duration)
        status_code = 200 if result["success"] else 400
        return jsonify(result), status_code
        
    except Exception as e:
        logger.error(f"API beep error: {e}")
        return jsonify({
            "success": False, 
            "message": "服务器内部错误",
            "code": "INTERNAL_ERROR"
        }), 500

@app.route('/api/stop', methods=['POST'])
def api_stop():
    """停止小车"""
    try:
        result = car_controller.stop()
        status_code = 200 if result["success"] else 400
        return jsonify(result), status_code
        
    except Exception as e:
        logger.error(f"API stop error: {e}")
        return jsonify({
            "success": False, 
            "message": "服务器内部错误",
            "code": "INTERNAL_ERROR"
        }), 500

# ===== 简化的GET接口（用于测试） =====

@app.route('/api/move/<int:state>/<int:speed>', methods=['GET'])
def api_move_simple(state, speed):
    """简化的运动控制接口 (GET)"""
    result = car_controller.move_car(state, speed)
    return jsonify(result)

@app.route('/api/trace/<int:mode>', methods=['GET'])
def api_trace_simple(mode):
    """简化的循迹控制接口 (GET)"""
    result = car_controller.send_trace_command(mode)
    return jsonify(result)

@app.route('/api/beep/<int:duration>', methods=['GET'])
def api_beep_simple(duration):
    """简化的蜂鸣器控制接口 (GET)"""
    result = car_controller.beep(duration)
    return jsonify(result)

@app.route('/api/stop', methods=['GET'])
def api_stop_simple():
    """简化的停止接口 (GET)"""
    result = car_controller.stop()
    return jsonify(result)

# ===== 错误处理 =====

@app.errorhandler(404)
def not_found(error):
    return jsonify({
        "success": False,
        "message": "API接口不存在",
        "code": "NOT_FOUND"
    }), 404

@app.errorhandler(405)
def method_not_allowed(error):
    return jsonify({
        "success": False,
        "message": "HTTP方法不被允许",
        "code": "METHOD_NOT_ALLOWED"
    }), 405

@app.errorhandler(500)
def internal_error(error):
    return jsonify({
        "success": False,
        "message": "服务器内部错误",
        "code": "INTERNAL_ERROR"
    }), 500

# ===== 启动服务器 =====

if __name__ == '__main__':
    print("=" * 60)
    print("🚗 智能巡检车后端API服务器")
    print("=" * 60)
    print(f"服务器地址: http://{CONFIG['HOST']}:{CONFIG['PORT']}")
    print(f"调试模式: {'开启' if CONFIG['DEBUG'] else '关闭'}")
    print()
    print("📋 API接口文档:")
    print("  健康检查: GET  /api/health")
    print("  状态查询: GET  /api/status")
    print("  运动控制: POST /api/move")
    print("  蜂鸣控制: POST /api/beep")
    print("  停止控制: POST /api/stop")
    print()
    print("🔧 测试接口:")
    print("  运动控制: GET  /api/move/<state>/<speed>")
    print("  蜂鸣控制: GET  /api/beep/<duration>")
    print("  停止控制: GET  /api/stop")
    print()
    print("📖 参数说明:")
    print("  state: 0=停止, 1=前进, 2=后退, 3=左转, 4=右转, 5=左旋, 6=右旋")
    print("  speed: 0-100 (速度百分比)")
    print("  duration: 蜂鸣时长(毫秒), 0=关闭, 1=持续")
    print()
    print("🌐 CORS: 已启用跨域支持")
    print("=" * 60)
    
    try:
        app.run(
            host=CONFIG["HOST"], 
            port=CONFIG["PORT"], 
            debug=CONFIG["DEBUG"],
            threaded=True
        )
    except KeyboardInterrupt:
        print("\n🛑 服务器正在关闭...")
        if car_controller.bot:
            car_controller.stop()
        print("✅ 服务器已停止")
    except Exception as e:
        logger.error(f"服务器启动失败: {e}")
        print(f"❌ 服务器启动失败: {e}")
